bitkeeper revision 1.15 (3e24a984iRiWWcgfKCxu2p5q3YbxXw)
authorkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Wed, 15 Jan 2003 00:21:24 +0000 (00:21 +0000)
committerkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Wed, 15 Jan 2003 00:21:24 +0000 (00:21 +0000)
Many files:
  First half of support for per-domain GDTs and LDTs

17 files changed:
xen-2.4.16/arch/i386/boot/boot.S
xen-2.4.16/arch/i386/entry.S
xen-2.4.16/arch/i386/mm.c
xen-2.4.16/arch/i386/process.c
xen-2.4.16/arch/i386/setup.c
xen-2.4.16/arch/i386/traps.c
xen-2.4.16/common/domain.c
xen-2.4.16/common/memory.c
xen-2.4.16/include/asm-i386/desc.h
xen-2.4.16/include/asm-i386/processor.h
xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h
xen-2.4.16/include/xeno/config.h
xen-2.4.16/include/xeno/mm.h
xen-2.4.16/include/xeno/sched.h
xenolinux-2.4.16-sparse/arch/xeno/kernel/process.c
xenolinux-2.4.16-sparse/arch/xeno/kernel/setup.c
xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h

index 7c9cff669b878f3295259449e27f9550e8bd9077..bd62d8ffba2825f517bdf768e15505cc756ee873 100644 (file)
@@ -225,11 +225,7 @@ ENTRY(gdt_table)
         .quad 0x00cff2000000bfff     /* 0x2b ring 3 3.95GB data at 0x0 */
         .quad 0x00cf9a000000ffff     /* 0x30 ring 0 4.00GB code at 0x0 */
         .quad 0x00cf92000000ffff     /* 0x38 ring 0 4.00GB data at 0x0 */
-        .quad 0x0000000000000000
-        .quad 0x0000000000000000
-        .quad 0x0000000000000000
-        .quad 0x0000000000000000
-        .fill NR_CPUS*4,8,0             /* space for TSS's and LDT's */
+        .fill NR_CPUS,8,0             /* space for TSS's */
 
 # The following adds 12kB to the kernel file size.
         .org 0x1000
index ea0a58f75f4ac8cdd598f5f5140f8136d65fecf6..910e1f19fcbda63c5f45fce5f0a31ae0ddcf794f 100644 (file)
@@ -516,8 +516,8 @@ ENTRY(hypervisor_call_table)
         .long SYMBOL_NAME(do_set_trap_table)
         .long SYMBOL_NAME(do_process_page_updates)
         .long SYMBOL_NAME(do_console_write)
-        .long SYMBOL_NAME(sys_ni_syscall)
-        .long SYMBOL_NAME(do_set_guest_stack)
+        .long SYMBOL_NAME(do_set_gdt)
+        .long SYMBOL_NAME(do_stack_and_ldt_switch)
         .long SYMBOL_NAME(do_net_update)
         .long SYMBOL_NAME(do_fpu_taskswitch)
         .long SYMBOL_NAME(do_yield)
@@ -526,6 +526,7 @@ ENTRY(hypervisor_call_table)
         .long SYMBOL_NAME(do_network_op)
         .long SYMBOL_NAME(do_set_debugreg)
         .long SYMBOL_NAME(do_get_debugreg)
+        .long SYMBOL_NAME(do_update_descriptor)
         .rept NR_syscalls-(.-hypervisor_call_table)/4
         .long SYMBOL_NAME(sys_ni_syscall)
        .endr
index fa62aed4f6c368351287c80093e5c610530209fc..2260882efca7b1f9a0f12a3ada7de6b70020117d 100644 (file)
@@ -91,7 +91,8 @@ void __init zap_low_mappings (void)
 }
 
 
-long do_set_guest_stack(unsigned long ss, unsigned long esp)
+long do_stack_and_ldt_switch(
+    unsigned long ss, unsigned long esp, unsigned long ldts)
 {
     int nr = smp_processor_id();
     struct tss_struct *t = &init_tss[nr];
@@ -99,6 +100,18 @@ long do_set_guest_stack(unsigned long ss, unsigned long esp)
     if ( (ss == __HYPERVISOR_CS) || (ss == __HYPERVISOR_DS) )
         return -1;
 
+    if ( ldts != current->mm.ldt_sel )
+    {
+        unsigned long *ptabent = GET_GDT_ADDRESS(current);
+        /* Out of range for GDT table? */
+        if ( (ldts * 8) > GET_GDT_ENTRIES(current) ) return -1;
+        ptabent += ldts * 2; /* 8 bytes per desc == 2 * unsigned long */
+        /* Not an LDT entry? (S=0b, type =0010b) */
+        if ( (*ptabent & 0x00001f00) != 0x00000200 ) return -1;
+        current->mm.ldt_sel = ldts;
+        __load_LDT(ldts);
+    }
+
     current->thread.ss1  = ss;
     current->thread.esp1 = esp;
     t->ss1  = ss;
@@ -106,3 +119,16 @@ long do_set_guest_stack(unsigned long ss, unsigned long esp)
 
     return 0;
 }
+
+
+long do_set_gdt(unsigned long *frame_list, int entries)
+{
+    return -ENOSYS;
+}
+
+
+long do_update_descriptor(
+    unsigned long pa, unsigned long word1, unsigned long word2)
+{
+    return -ENOSYS;
+}
index 11cd5a1c23379ecdf21987581e5df19bdd244c88..c8e81de6750d3ddc8271b6999bda086ccd921621 100644 (file)
@@ -380,6 +380,10 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
     asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
     asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
 
+    /* Switch GDT and LDT. */
+    __asm__ __volatile__ ("lgdt %0" : "=m" (*next_p->mm.gdt));
+    __load_LDT(next_p->mm.ldt_sel);
+
     /*
      * Restore %fs and %gs.
      */
index e23ca04ea465ded925bf126596aeeaca6384f145..a03c4bac4d1296b9be8be37720ddb06b647f0dc5 100644 (file)
@@ -194,7 +194,10 @@ void __init cpu_init(void)
         panic("CPU#%d already initialized!!!\n", nr);
     printk("Initializing CPU#%d\n", nr);
 
-    __asm__ __volatile__("lgdt %0": "=m" (gdt_descr));
+    /* Set up GDT and IDT. */
+    SET_GDT_ENTRIES(current, DEFAULT_GDT_ENTRIES);
+    SET_GDT_ADDRESS(current, DEFAULT_GDT_ADDRESS);
+    __asm__ __volatile__("lgdt %0": "=m" (*current->mm.gdt));
     __asm__ __volatile__("lidt %0": "=m" (idt_descr));
 
     /* No nested task. */
index 85dd1bc93ad72e1e106bb2576d0314384281495b..0ce294c9f48105aab283511c68929dbf4286612f 100644 (file)
@@ -514,11 +514,6 @@ void set_tss_desc(unsigned int n, void *addr)
     _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89);
 }
 
-void set_ldt_desc(unsigned int n, void *addr, unsigned int size)
-{
-    _set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82);
-}
-
 void __init trap_init(void)
 {
     set_trap_gate(0,&divide_error);
index 90c1a0a779afc373cdec3012661ca7d68a76b60d..31ae0b97262afda24e07c40f99c02027d25428fa 100644 (file)
@@ -43,7 +43,10 @@ struct task_struct *do_newdomain(void)
     if (!p) goto newdomain_out;
     memset(p, 0, sizeof(*p));
     p->shared_info = (void *)get_free_page(GFP_KERNEL);
-    memset(p->shared_info, 0, sizeof(shared_info_t));
+    memset(p->shared_info, 0, PAGE_SIZE);
+
+    SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
+    SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS);
 
     p->addr_limit = USER_DS;
     p->state      = TASK_UNINTERRUPTIBLE;
@@ -247,6 +250,7 @@ void release_task(struct task_struct *p)
     {
         destroy_net_vif(p);
     }
+    if ( p->mm.perdomain_pt ) free_page((unsigned long)p->mm.perdomain_pt);
     free_page((unsigned long)p->shared_info);
     free_task_struct(p);
 }
@@ -462,6 +466,8 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params)
     phys_l2tab = ALLOC_FRAME_FROM_DOMAIN();
     l2tab = map_domain_mem(phys_l2tab);
     memcpy(l2tab, idle_pg_table[p->processor], PAGE_SIZE);
+    l2tab[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
+        mk_l2_pgentry(__pa(p->mm.perdomain_pt) | __PAGE_HYPERVISOR);
     memset(l2tab, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE*sizeof(l2_pgentry_t));
     p->mm.pagetable = mk_pagetable(phys_l2tab);
 
index 8cb80c694a5fa2099822271865d99c178044a4d6..226772ebceaf6456a15c588a0874b07e2f6f103c 100644 (file)
@@ -329,6 +329,9 @@ static int get_l2_table(unsigned long page_nr)
     memcpy(p_l2_entry, 
            idle_pg_table[smp_processor_id()] + DOMAIN_ENTRIES_PER_L2_PAGETABLE,
            HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
+    p_l2_entry[(PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT) -
+              DOMAIN_ENTRIES_PER_L2_PAGETABLE] =
+        mk_l2_pgentry(__pa(current->mm.perdomain_pt) | __PAGE_HYPERVISOR);
 
     return(ret);
 }
index 3855ebcb6c6943e74b1cd59ecd492b96467011f4..2cb90769b5226189a48a157d09c86a36edcb34a0 100644 (file)
@@ -1,11 +1,8 @@
 #ifndef __ARCH_DESC_H
 #define __ARCH_DESC_H
 
-#define __FIRST_TSS_ENTRY 12
-#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY+1)
-
-#define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY)
-#define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY)
+#define __FIRST_TSS_ENTRY 8
+#define __TSS(n) ((n) + __FIRST_TSS_ENTRY)
 
 #ifndef __ASSEMBLY__
 struct desc_struct {
@@ -25,10 +22,9 @@ struct Xgt_desc_struct {
 
 #define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3))
 
-#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3))
+#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" ((n)<<3))
 
 extern void set_intr_gate(unsigned int irq, void * addr);
-extern void set_ldt_desc(unsigned int n, void *addr, unsigned int size);
 extern void set_tss_desc(unsigned int n, void *addr);
 
 #endif /* !__ASSEMBLY__ */
index 2e98c531342345e0fd960b702ea53239e90c3ba4..b3f496c5bc79dcad1dcc84985d5b6ada36b7a031 100644 (file)
@@ -375,7 +375,7 @@ struct thread_struct {
        0,0,0,0, /* esp,ebp,esi,edi */                          \
        0,0,0,0,0,0, /* es,cs,ss */                             \
        0,0,0,0,0,0, /* ds,fs,gs */                             \
-       __LDT(0),0, /* ldt */                                   \
+       0,0, /* ldt */                                          \
        0, INVALID_IO_BITMAP_OFFSET, /* tace, bitmap */         \
        {~0, } /* ioperm */                                     \
 }
index 1e3705e9acc5b5d054fd51a28ef45730ec3d0133..226601d62ae572ee23fc7ca19b211a4188fd5ede 100644 (file)
@@ -51,21 +51,34 @@ typedef struct
 } page_update_request_t;
 
 
+/*
+ * Segment descriptor tables.
+ */
+/* 8 entries, plus a TSS entry for each CPU (up to 32 CPUs). */
+#define FIRST_DOMAIN_GDT_ENTRY  40
+/* These are flat segments for domain bootstrap and fallback. */
+#define FLAT_RING1_CS           0x11
+#define FLAT_RING1_DS           0x19
+#define FLAT_RING3_CS           0x23
+#define FLAT_RING3_DS           0x2b
+
+
 /* EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5. */
 
-#define __HYPERVISOR_set_trap_table  0
-#define __HYPERVISOR_pt_update       1
-#define __HYPERVISOR_console_write   2
-/* vector 3 unused */
-#define __HYPERVISOR_set_guest_stack 4
-#define __HYPERVISOR_net_update      5
-#define __HYPERVISOR_fpu_taskswitch  6
-#define __HYPERVISOR_yield           7
-#define __HYPERVISOR_exit            8
-#define __HYPERVISOR_dom0_op         9
-#define __HYPERVISOR_network_op     10
-#define __HYPERVISOR_set_debugreg   11
-#define __HYPERVISOR_get_debugreg   12
+#define __HYPERVISOR_set_trap_table        0
+#define __HYPERVISOR_pt_update             1
+#define __HYPERVISOR_console_write         2
+#define __HYPERVISOR_set_gdt               3
+#define __HYPERVISOR_stack_and_ldt_switch  4
+#define __HYPERVISOR_net_update            5
+#define __HYPERVISOR_fpu_taskswitch        6
+#define __HYPERVISOR_yield                 7
+#define __HYPERVISOR_exit                  8
+#define __HYPERVISOR_dom0_op               9
+#define __HYPERVISOR_network_op           10
+#define __HYPERVISOR_set_debugreg         11
+#define __HYPERVISOR_get_debugreg         12
+#define __HYPERVISOR_update_descriptor    13
 
 #define TRAP_INSTR "int $0x82"
 
index ccbbd1d325a78a90b8c31cfc3059a08600b84c1e..f139a80066bc8c02b72854af3541e7c1418a58b8 100644 (file)
 #define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
 #define ____cacheline_aligned __cacheline_aligned
 
-/* 0-16MB is fixed monitor space. 0-56MB is direct-mapped at top of memory.*/
+/* 0-16MB is fixed monitor space. 0-52MB is direct-mapped at top of memory.*/
 #define MAX_MONITOR_ADDRESS   (16*1024*1024)
 #define MAX_DMA_ADDRESS       (16*1024*1024)
-#define MAX_DIRECTMAP_ADDRESS (56*1024*1024)
+#define MAX_DIRECTMAP_ADDRESS (52*1024*1024)
+/* Next 4MB of virtual address space used for per-domain mappings (eg. GDT). */
+#define PERDOMAIN_VIRT_START  (PAGE_OFFSET + MAX_DIRECTMAP_ADDRESS)
+#define PERDOMAIN_VIRT_END    (PERDOMAIN_VIRT_START + (4*1024*1024))
 /* Penultimate 4MB of virtual address space used for domain page mappings. */
-#define MAPCACHE_VIRT_START   (PAGE_OFFSET + MAX_DIRECTMAP_ADDRESS)
+#define MAPCACHE_VIRT_START   (PERDOMAIN_VIRT_END)
 #define MAPCACHE_VIRT_END     (MAPCACHE_VIRT_START + (4*1024*1024))
 /* Final 4MB of virtual address space used for ioremap(). */
 #define IOREMAP_VIRT_START    (MAPCACHE_VIRT_END)
index 93b66c7007443373eb3c9bdca57b46bdf0551a9d..30071e76cfc659c0c25caf7668e10358c65dde74 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <xeno/config.h>
 #include <asm/atomic.h>
+#include <asm/desc.h>
 #include <xeno/list.h>
 #include <hypervisor-ifs/hypervisor-if.h>
 
@@ -89,13 +90,15 @@ typedef struct pfn_info {
  * references exist of teh current type. A change in type can only occur
  * when type_count == 0.
  */
-#define PG_type_mask        (7<<25) /* bits 25-27 */
-#define PGT_none            (0<<25) /* no special uses of this page */
-#define PGT_l1_page_table   (1<<25) /* using this page as an L1 page table? */
-#define PGT_l2_page_table   (2<<25) /* using this page as an L2 page table? */
-#define PGT_l3_page_table   (3<<25) /* using this page as an L3 page table? */
-#define PGT_l4_page_table   (4<<25) /* using this page as an L4 page table? */
-#define PGT_writeable_page  (7<<25) /* has writable mappings of this page? */
+#define PG_type_mask        (7<<24) /* bits 24-26 */
+#define PGT_none            (0<<24) /* no special uses of this page */
+#define PGT_l1_page_table   (1<<24) /* using this page as an L1 page table? */
+#define PGT_l2_page_table   (2<<24) /* using this page as an L2 page table? */
+#define PGT_l3_page_table   (3<<24) /* using this page as an L3 page table? */
+#define PGT_l4_page_table   (4<<24) /* using this page as an L4 page table? */
+#define PGT_gdt_page        (5<<24) /* using this page in a GDT? */
+#define PGT_ldt_page        (6<<24) /* using this page in an LDT? */
+#define PGT_writeable_page  (7<<24) /* has writable mappings of this page? */
 
 #define PageSlab(page)         test_bit(PG_slab, &(page)->flags)
 #define PageSetSlab(page)      set_bit(PG_slab, &(page)->flags)
@@ -114,4 +117,7 @@ void init_frametable(unsigned long nr_pages);
 /* Part of the domain API. */
 int do_process_page_updates(page_update_request_t *updates, int count);
 
+#define DEFAULT_GDT_ENTRIES     ((FIRST_DOMAIN_GDT_ENTRY*8)-1)
+#define DEFAULT_GDT_ADDRESS     ((unsigned long)gdt_table)
+
 #endif /* __XENO_MM_H__ */
index 295335bd1604b200f0646265d22eb35c21e6f820..3871faa2f18481261e00027c225c61794e32c847 100644 (file)
@@ -19,13 +19,29 @@ extern rwlock_t tasklist_lock;
 
 struct mm_struct {
     unsigned long cpu_vm_mask;
+    /*
+     * Every domain has a L1 pagetable of its own. Per-domain mappings
+     * are put in this table (eg. the current GDT is mapped here).
+     */
+    l2_pgentry_t *perdomain_pt;
     pagetable_t  pagetable;
+    /* Current LDT selector. */
+    unsigned int ldt_sel;
+    /* Next entry is passed to LGDT on domain switch. */
+    char gdt[6];
 };
 
+/* Convenient accessor for mm.gdt. */
+#define SET_GDT_ENTRIES(_p, _e) ((*(u16 *)((_p)->mm.gdt + 0)) = (_e))
+#define SET_GDT_ADDRESS(_p, _a) ((*(u32 *)((_p)->mm.gdt + 2)) = (_a))
+#define GET_GDT_ENTRIES(_p)     ((*(u16 *)((_p)->mm.gdt + 0)))
+#define GET_GDT_ADDRESS(_p)     ((*(u32 *)((_p)->mm.gdt + 2)))
+
 extern struct mm_struct init_mm;
 #define IDLE0_MM                                                    \
 {                                                                   \
     cpu_vm_mask: 0,                                                 \
+    perdomain_pt: 0,                                                \
     pagetable:   mk_pagetable(__pa(idle0_pg_table))                 \
 }
 
index 9e26f3d65aca7ac8880e37b0d7fee54eee447ae2..1c7f27176d703799947135f43f34fdbad4430fd8 100644 (file)
@@ -337,7 +337,7 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 
     unlazy_fpu(prev_p);
 
-    HYPERVISOR_set_guest_stack(__KERNEL_DS, next->esp0);
+    HYPERVISOR_stack_and_ldt_switch(__KERNEL_DS, next->esp0, 0);
 
     /*
      * Save away %fs and %gs. No need to save %es and %ds, as
index 082bc318391ffa9ec951ca142d50f0b273f3295a..2bef924df0f0755a4917b484556a4074750b2bb2 100644 (file)
@@ -954,7 +954,7 @@ void __init cpu_init (void)
         BUG();
     enter_lazy_tlb(&init_mm, current, nr);
 
-    HYPERVISOR_set_guest_stack(__KERNEL_DS, current->thread.esp0);
+    HYPERVISOR_stack_and_ldt_switch(__KERNEL_DS, current->thread.esp0, 0);
 
     /* Force FPU initialization. */
     current->flags &= ~PF_USEDFPU;
index 839feed153d9180003b5ed500495b8d4cbe75a43..640c3a958e54d3bbad3d95902962e058c8648ff0 100644 (file)
@@ -171,14 +171,26 @@ static inline int HYPERVISOR_console_write(const char *str, int count)
     return ret;
 }
 
-static inline int HYPERVISOR_set_guest_stack(
-    unsigned long ss, unsigned long esp)
+static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
 {
     int ret;
     __asm__ __volatile__ (
         TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_set_guest_stack),
-        "b" (ss), "c" (esp) );
+        : "=a" (ret) : "0" (__HYPERVISOR_set_gdt), 
+        "b" (frame_list), "c" (entries) );
+
+
+    return ret;
+}
+
+static inline int HYPERVISOR_stack_and_ldt_switch(
+    unsigned long ss, unsigned long esp, unsigned long ldts)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret) : "0" (__HYPERVISOR_stack_and_ldt_switch),
+        "b" (ss), "c" (esp), "d" (ldts) );
 
     return ret;
 }
@@ -267,4 +279,17 @@ static inline unsigned long HYPERVISOR_get_debugreg(int reg)
     return ret;
 }
 
+static inline int HYPERVISOR_update_descriptor(
+    unsigned long pa, unsigned long word1, unsigned long word2)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret) : "0" (__HYPERVISOR_set_gdt), 
+        "b" (pa), "c" (word1), "d" (word2) );
+
+
+    return ret;
+}
+
 #endif /* __HYPERVISOR_H__ */